﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BoolanSlide.RedoUndo;
using Configuration;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
using Shapes = Windows.UI.Xaml.Shapes;

namespace BoolanElement
{
    public class BooEllipseDialog:BooTextShapesBase
    {
        Shapes.Path ellipseDialog;
        public Shapes.Path EllipseDialog
        {
            get { return ellipseDialog; }
            set { ellipseDialog = value; }
        }

        public PathFigure DialogFigure
        {
            get { return ((PathGeometry)ellipseDialog.Data).Figures[0]; }
            set { ((PathGeometry)ellipseDialog.Data).Figures[0] = value; }
        }

        public ArcSegment EllipseArc
        {
            get { return (ArcSegment)((PathGeometry)ellipseDialog.Data).Figures[0].Segments[0]; }
            set { ((PathGeometry)ellipseDialog.Data).Figures[0].Segments[0] = value; }
        }

        public LineSegment Line1
        {
            get { return (LineSegment)((PathGeometry)ellipseDialog.Data).Figures[0].Segments[1]; }
            set { ((PathGeometry)ellipseDialog.Data).Figures[0].Segments[1] = value; }
        }

        public LineSegment Line2
        {
            get { return (LineSegment)((PathGeometry)ellipseDialog.Data).Figures[0].Segments[2]; }
            set { ((PathGeometry)ellipseDialog.Data).Figures[0].Segments[2] = value; }
        }
        
        BooEllipseDialogElement ellipseDialogElement;
        public BooEllipseDialogElement EllipseDialogElement
        {     
            get { return ellipseDialogElement; }
        }

        public override BooElement Element
        {
            set { ellipseDialogElement = (BooEllipseDialogElement)value; }
            get { return ellipseDialogElement; }
        }

        public override BooTextShapesBaseElement TextShapesBaseElement
        {
            get { return ellipseDialogElement; }
        }

        public override Shapes.Shape Shape
        {
            get { return ellipseDialog; }
        }

        public Canvas ArrowControlPoint;

        public BooEllipseDialog(BooEllipseDialogElement element, SaveForRedoUndo saveForRedoUndo)
            :base(element)
        {
            this.ellipseDialogElement = element;
            InitOriginal();
            InitializeControlPoint();
            base.saveForRedoUndo = saveForRedoUndo;
            Focus.InitFocusEvent(this);
        }

        public BooEllipseDialog(BooEllipseDialogElement element)
            :base(element)
        {
            this.ellipseDialogElement = element;
            InitOriginalForThumbNails();
            InitializeControlPoint();
        }

        public override void InitShape()
        {
            ellipseDialog = CreateDialog(ellipseDialogElement.ShapeWidth, ellipseDialogElement.ShapeHeight, this.ellipseDialogElement.Line1Point);

            this.ellipseDialogElement.ArcStartPoint = DialogFigure.StartPoint;
            this.ellipseDialogElement.ArcEndPoint = EllipseArc.Point;
            this.ellipseDialogElement.ArcSize = EllipseArc.Size;
            this.ellipseDialogElement.Line1Point = Line1.Point;
            this.ellipseDialogElement.Line2Point = Line2.Point;
        }

        private void InitializeControlPoint()
        {
            ArrowControlPoint = new Canvas();
            Ellipse elli = new Ellipse();
            elli.Width = FocusEllipses.FocusEllipsesDiameter;
            elli.Height = FocusEllipses.FocusEllipsesDiameter;
            SolidColorBrush fillColor = new SolidColorBrush(ConstColor.TitleColor);
            SolidColorBrush strokeColor = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
            elli.Fill = fillColor;
            elli.Stroke = strokeColor;
            elli.StrokeThickness = 1;
            ArrowControlPoint.Children.Add(elli);
            ArrowControlPoint.Width = 50;
            ArrowControlPoint.Height = 50;
            ArrowControlPoint.Background = new SolidColorBrush(Colors.Transparent);
            ArrowControlPoint.RenderTransform = new TranslateTransform();
            (ArrowControlPoint.RenderTransform as TranslateTransform).X = Line1.Point.X - ArrowControlPoint.Width / 2;
            (ArrowControlPoint.RenderTransform as TranslateTransform).Y = Line1.Point.Y - ArrowControlPoint.Height / 2;
            elli.RenderTransform = new TranslateTransform()
            {
                X = (ArrowControlPoint.Width - elli.Width) / 2,
                Y = (ArrowControlPoint.Height - elli.Height) / 2
            };
            BooCanvas.Children.Add(ArrowControlPoint);
            ArrowControlPoint.ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY;
            ArrowControlPoint.ManipulationDelta += ArrowControlPoint_ManipulationDelta;
            ArrowControlPoint.ManipulationCompleted += ArrowControlPoint_ManipulationCompleted;
            ArrowControlPoint.Visibility = Visibility.Collapsed;
        }

        void ArrowControlPoint_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        void ArrowControlPoint_ManipulationDelta(object sender, Windows.UI.Xaml.Input.ManipulationDeltaRoutedEventArgs e)
        {

            double width = e.Delta.Translation.X;
            double height = e.Delta.Translation.Y;
            double angle = this.Element.ElementTransform.Rotate.Angle * Math.PI / 180;
            double marginX = height * Math.Sin(angle) + width * Math.Cos(angle);
            double marginY = height * Math.Cos(angle) - width * Math.Sin(angle);
            Point orig = Line1.Point;
            orig.X += marginX;
            orig.Y += marginY;
            (ArrowControlPoint.RenderTransform as TranslateTransform).X += marginX;
            (ArrowControlPoint.RenderTransform as TranslateTransform).Y += marginY;
            ModifyDialog(ellipseDialog,ellipseDialogElement.ShapeWidth, ellipseDialogElement.ShapeHeight,GetPoints(ellipseDialogElement.ShapeWidth, ellipseDialogElement.ShapeHeight,orig));
            this.ellipseDialogElement.ArcStartPoint = DialogFigure.StartPoint;
            this.ellipseDialogElement.ArcEndPoint = EllipseArc.Point;
            this.ellipseDialogElement.ArcSize = EllipseArc.Size;
            this.ellipseDialogElement.Line1Point = Line1.Point;
            this.ellipseDialogElement.Line2Point = Line2.Point;

            ellipseDialogElement.PropertyChanged("Shape");
            e.Handled = true;
        }

        public double GetAngleWithLineAndEllipse(Point centerPoint, Point outerPoint, double longAxis, double shortAxis)
        {
            double angle = 0;
            Point vec = new Point(outerPoint.X - centerPoint.X, outerPoint.Y - centerPoint.Y);
            if (Math.Abs(vec.X) > 1)
            {
                double tanAngle = (longAxis / 2 * (outerPoint.Y - centerPoint.Y)) / (shortAxis / 2 * (outerPoint.X - centerPoint.X));
                angle = Math.Abs(Math.Atan(tanAngle));
            }
            if (vec.X > 1)
            {
                if (vec.Y < 0)
                {
                    angle = Math.PI * 2 - angle;
                }
            }
            else if (vec.X < -1)
            {
                if (vec.Y > 0)
                {
                    angle = Math.PI - angle;
                }
                else
                {
                    angle = Math.PI + angle;
                }
            }
            else
            {
                if (vec.Y > 0)
                {
                    angle = Math.PI * 1 / 2;
                }
                else
                {
                    angle = Math.PI;
                }
            }
            return angle * 180 / Math.PI;
        }

        public Point GetEllipsePoint(Point centerPoint, double longAxis, double shortAxis, double angle)
        {
            double x = longAxis / 2 * Math.Cos(angle * Math.PI / 180) + centerPoint.X;
            double y = shortAxis / 2 * Math.Sin(angle * Math.PI / 180) + centerPoint.Y;
            return new Point(x, y);
        }

        public Point[] GetPoints(double width, double height, Point pointer)
        {
            double angle = GetAngleWithLineAndEllipse(new Point(width / 2, height / 2), pointer, width, height);
            Point[] points = new Point[3];
            points[0] = GetEllipsePoint(new Point(width / 2, height / 2), width, height, angle + 10);
            points[1] = pointer;
            points[2] = GetEllipsePoint(new Point(width / 2, height / 2), width, height, angle - 10);

            return points;
        }

        public Windows.UI.Xaml.Shapes.Path CreateDialog(double width, double height, Point pointer)
        {
            Point[] points = GetPoints(width, height, pointer);
            Windows.UI.Xaml.Shapes.Path path = new Windows.UI.Xaml.Shapes.Path();
            path.Stroke = new SolidColorBrush(Colors.Pink);
            path.StrokeThickness = 5;
            PathGeometry pathGeometry = new PathGeometry();
            PathFigure figure = new PathFigure();
            figure.IsClosed = true;
            figure.StartPoint = points[0];
            ArcSegment arc = new ArcSegment();
            arc.IsLargeArc = true;
            arc.Point = points[2];
            arc.Size = new Size(width/2, height/2);
            arc.SweepDirection = SweepDirection.Clockwise;
            figure.Segments.Add(arc);

            LineSegment line1 = new LineSegment();
            line1.Point = points[1];
            figure.Segments.Add(line1);

            LineSegment line2 = new LineSegment();
            line2.Point = points[0];
            figure.Segments.Add(line2);

            pathGeometry.Figures.Add(figure);
            path.Data = pathGeometry;
            return path;
        }

        public void ModifyDialog(Windows.UI.Xaml.Shapes.Path orig, double width,double height,Point[] points)
        {
            PathGeometry pathGeometry = orig.Data as PathGeometry;
            PathFigure figure = pathGeometry.Figures[0];
            figure.StartPoint = points[0];
            ArcSegment arc = figure.Segments[0] as ArcSegment;
            arc.Size = new Size(width/2,height/2);
            arc.Point = points[2];

            LineSegment line1 = figure.Segments[1] as LineSegment;
            line1.Point = points[1];

            LineSegment line2 = figure.Segments[2] as LineSegment;
            line2.Point = points[0];
        }


        public override void ReSizeUI(double x, double y)
        {
            if (ellipseDialogElement.ElementTransform.Width + x < 50 || ellipseDialogElement.ElementTransform.Height + y < 50)
            {
                return;
            }

            ellipseDialogElement.ElementTransform.Width = ellipseDialogElement.ElementTransform.Width + x;
            ellipseDialogElement.ElementTransform.Height = ellipseDialogElement.ElementTransform.Height + y;

            ellipseDialogElement.ShapeWidth = ellipseDialogElement.ElementTransform.Width;
            ellipseDialogElement.ShapeHeight = ellipseDialogElement.ElementTransform.Height;

            ellipseDialogElement.PropertyChanged("Shape");
        }

        public override void ApplySize()
        {
            base.ApplySize();
            FullGrid.Width = ellipseDialogElement.ElementTransform.Width;
            FullGrid.Height = ellipseDialogElement.ElementTransform.Height;

            BooCanvas.Width = ellipseDialogElement.ElementTransform.Width;
            BooCanvas.Height = ellipseDialogElement.ElementTransform.Height;

            CenterStack.Width = ellipseDialogElement.ElementTransform.Width;
            //CenterStack.MaxHeight = ellipseDialogElement.ElementTransform.Height;


            this.TextBox.Width = ellipseDialogElement.ElementTransform.Width;
            ellipseDialogElement.TextWidth = ellipseDialogElement.ElementTransform.Width;
            //this.TextBox.M/axHeight = ellipseDialogElement.ElementTransform.Height;
            //ellipseDialogElement.TextMaxHeight = ellipseDialogElement.ElementTransform.Height;

            Focus.FocusElls.ScopeRectangle.Width = ellipseDialogElement.ElementTransform.Width;
            Focus.FocusElls.ScopeRectangle.Height = ellipseDialogElement.ElementTransform.Height;
            Focus.SetFocuseEllipseMargin(ellipseDialogElement.ElementTransform.Width, ellipseDialogElement.ElementTransform.Height);

            ModifyDialog(ellipseDialog, ellipseDialogElement.ShapeWidth, ellipseDialogElement.ShapeHeight, GetPoints(ellipseDialogElement.ShapeWidth, ellipseDialogElement.ShapeHeight, this.ellipseDialogElement.Line1Point));
        }

        public override void ReMargin(double x, double y)
        {
            this.Element.ElementTransform.Translate.X += x;
            this.Element.ElementTransform.Translate.Y += y;
        }

        public override void GotFocus()
        {
            base.GotFocus();
            if (ArrowControlPoint != null)
            {
                ArrowControlPoint.Visibility = Visibility.Visible;
            }
        }

        public override void LostFocus()
        {
            base.LostFocus();
            if (ArrowControlPoint != null)
            {
                ArrowControlPoint.Visibility = Visibility.Collapsed;
            }
        }

    }
}
